﻿// Original author contact info: Owen Emlen (owene_1998@yahoo.com)
// Note: other individuals may also have contributed to this code
// Project hosted on CodePlex.com as of 1/10/2009 at http://www.codeplex.com/EmlenMud
using System.Runtime.Serialization;
using System;
using System.Threading;
using System.Reflection;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BrainTechLLC.ThreadSafeObjects;

namespace BrainTechLLC
{    
    public class FleeCommand : Command, ICommandInfo
    {
        public override string HelpText { get { return "Attempts to flee from the person or creature you are currently fighting"; } }

        public static List<string> Words = new List<string>() { "FLEE" };

        public override List<string> FirstWords { get { return Words; } }

        public override CommandToPerform CreateCommand(IGameThing source, string first, string input)
        {
            CommandToPerform cmd = CommandFactory.CreateFlee(source.AssociatedID);
            return cmd;
        }

        public override bool CheckIsValid(IGameThing source, string first, string input)
        {
            return true;
        }

        [MethodVisible]
        public static EventToPerceive CreateFleeObservableEvent(GameChar source, GeneralDirection dir)
        {
            return new GeneralEventToPerceive()
            {
                ShowToSource = new Event("You flee " + dir.DirectionText() + ".", ViewType.See),
                ShowToObservers = new Event("~source flees " + dir.DirectionText() + ".", ViewType.See),
                Sources = new AssociatedIDCollection(source.AssociatedID),
            };
        }

        [MethodVisible]
        public static string CanFlee(CommandToPerform cmd, IGameThing src, IGameThing tar, PropertyData args, PropertyData modifyingArguments)
        {
            GameChar source = src as GameChar;

            if (source == null)
                return "Error";

            if (source.IsDead)
                return "You are dead.";

            GeneralDirection dirFlee = GeneralDirection.None.GetRandom(GeneralDirection.SE);

            int n = 0;
            while (!source.GameLocation.HasEdge(dirFlee))
            {
                if (n++ >= 4)
                    break;

                dirFlee = GeneralDirection.None.GetRandom();
            }

            if (!source.GameLocation.HasEdge(dirFlee))
                return "You are unable to flee!";

            var val = args.GetReference("FleeDirection");
            val.Value = dirFlee;

            return string.Empty;
        }

        [MethodVisible]
        public static List<PerceivedEventAndAudience> Flee(CommandToPerform cmd, IGameThing src, IGameThing tar, PropertyData args, PropertyData modifyingArguments)
        {
            GameChar source = src as GameChar;
            List<PerceivedEventAndAudience> events = new List<PerceivedEventAndAudience>();
            GeneralDirection dirFlee = args.GetArgument<GeneralDirection>("FleeDirection");
            
            // Do actual fleeing here
            CombatHandler.StopAttacking(source, true);
            args.Add("Direction", new IdentifierAndValue("Direction", dirFlee));
            
            MoveCommand.Move(null, source, tar, args, modifyingArguments);

            EventToPerceive evt = CreateFleeObservableEvent(source, dirFlee);
            events.Add(new PerceivedEventAndAudience() { Event = evt, Audience = source.GameLocation.Things });

            if (source.Settings.GetArgument<bool>("LookAfterMove"))
            {
                cmd.AdditionalCommand = CommandFactory.CreateLook(source.AssociatedID, string.Empty);
            }

            return events;
        }
    }

    public static partial class CommandFactory
    {
        [MethodVisible]
        public static CommandToPerform CreateFlee(long source)
        {
            CommandToPerform cmd = new CommandToPerform()
            {
                ApplyToID = source,
                Arguments = new PropertyData(new IdentifierAndValue() { Identifier = "FleeDirection", Value = GeneralDirection.None }),
                CheckPermittedMethod = new Method("FleeCommand", "CanFlee"),
                PerformMethod = new Method("FleeCommand", "Flee")
            };
            return cmd;
        }
    }
}
